package com.flaskpy.web.eternity.auth.jwt.context;


import com.flaskpy.web.eternity.auth.jwt.config.JwtConfigProperties;
import com.flaskpy.web.eternity.auth.jwt.constant.CommonConstant;
import com.flaskpy.web.eternity.auth.jwt.entiry.JwtPayLoad;
import com.flaskpy.web.eternity.auth.jwt.service.IJwtAuthicationService;
import com.flaskpy.web.eternity.auth.jwt.service.IOnLineService;
import com.flaskpy.web.eternity.auth.jwt.util.TokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@RequiredArgsConstructor
@Component
public class JwtContextHolder {


    private static AuthenticationManagerBuilder authenticationManagerBuilder;
    private static IJwtAuthicationService jwtAuthicationService;
    private static TokenProvider tokenProvider;
    private static JwtConfigProperties configProperties;
    private static IOnLineService onLineService;

    /**
     * jwt登陆
     * @param usernamePasswordAuthenticationToken
     * @return
     */
    public static Authentication login(UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken){
        /*
        * 原理：UsernamePassword强行塞进authenticationMamager
        * 别走什么过滤器 让系统自带的DaoAuthenticationProvider 证证
        * userDetailService 照样走流程。
        * 返回的Authentication已被系统填满数据，转为JwtPayLoad再转 token字符串
        * 给客户端，客户端每 次请求带上后ContextRepository会重新生成JwtPayLoad
        * 其他流程按常规走
        *
        * */
        Authentication authentication = JwtContextHolder.authenticationManagerBuilder.getObject().authenticate(usernamePasswordAuthenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        JwtPayLoad jwtPayLoad = jwtAuthicationService.toJwtContentDTO(authentication);
        String token=tokenProvider.jwtContentToToken(jwtPayLoad);

        request.setAttribute(CommonConstant.JWT_DTO,jwtPayLoad);
        request.setAttribute(CommonConstant.JWT_TOKEN,token);
        onLineService.login(token,authentication);
        return authentication;
    }

    /**
     * jwt退出
     */
    public  static  void logout(){
        onLineService.logout(currentJwtToken());
    }

    public static Authentication currentAuthentication(){

        return SecurityContextHolder.getContext().getAuthentication();
    }

    /**
     * 当前jwt载体
     * @return
     */
    public static JwtPayLoad currentJwtPayload(){
        HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        return (JwtPayLoad)request.getAttribute(CommonConstant.JWT_DTO);
    }

    /**
     * 当前token
     * @return
     */
    public static String currentJwtToken(){
        HttpServletRequest request =((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        return (String)request.getAttribute(CommonConstant.JWT_TOKEN);

    }

    public static JwtConfigProperties getConfigProperties(){
        return configProperties;
    }
    @Autowired
    public void setAuthenticationManagerBuilder(AuthenticationManagerBuilder authenticationManagerBuilder){
        JwtContextHolder.authenticationManagerBuilder=authenticationManagerBuilder;
    }
    @Autowired
    public void setJwtAuthicationService(IJwtAuthicationService iJwtAuthicationService){
        JwtContextHolder.jwtAuthicationService=iJwtAuthicationService;
    }
    @Autowired
    public void setConfigProperties(JwtConfigProperties configProperties){
        JwtContextHolder.configProperties=configProperties;
    }
    @Autowired
    public void setTokenProvider(TokenProvider tokenProvider){
        JwtContextHolder.tokenProvider=tokenProvider;
    }
    @Autowired
    public  void setOnLineService(IOnLineService onLineService){
        JwtContextHolder.onLineService=onLineService;
    }
}
